{ *********************************************************************** }
{                                                                         }
{ MemUtils                                                                }
{                                                                         }
{ Copyright (c) 2003-2004 Pisarev Yuriy (mail@pisarev.net)                }
{                                                                         }
{ *********************************************************************** }

unit MemUtils;

{$B-}
{$WARN SYMBOL_PLATFORM OFF}

interface

uses Windows, SysUtils, Math;

type
  TByteArray = array of Byte;
  TIntArray = array of Integer;
  TInt64Array = array of Int64;

procedure SetRandom(var IntArray: TIntArray);

function IndexOf(const Source, Value; ItemSize, ItemCount: Integer): Integer; overload;
function IndexOf(const Int64Array: TInt64Array; Value: Int64): Integer; overload;
function IndexOf(const IntArray: TIntArray; Value: Integer): Integer; overload;
function IndexOf(const ByteArray: TByteArray; Value: Byte): Integer; overload;

function Delete(var Source, Target; ItemSize, ItemCount, ItemIndex: Integer): Boolean; overload;
function Delete(var Int64Array: TInt64Array; Index: Integer): Boolean; overload;
function Delete(var IntArray: TIntArray; Index: Integer): Boolean; overload;
function Delete(var ByteArray: TByteArray; Index: Integer): Boolean; overload;

procedure Append(const Source; var Target; ItemSize, SourceItemCount,
  TargetItemCount: Integer); overload;
procedure Append(var Int64Array: TIntArray; const NewArray: TInt64Array); overload;
procedure Append(var IntArray: TIntArray; const NewArray: TIntArray); overload;
procedure Append(var ByteArray: TIntArray; const NewArray: TByteArray); overload;

implementation

procedure SetRandom(var IntArray: TIntArray);
var
  I, J, K: Integer;
  Data: TIntArray;
begin
  SetLength(Data, Length(IntArray));
  try
    for I := Low(Data) to High(Data) do Data[I] := I;
    I := 0;
    K := Length(Data);
    while K > 0 do
    begin
      J := Random(K);
      IntArray[I] := Data[J];
      Delete(Data, J);
      Inc(I);
      K := Length(Data);
    end;
  except
    Data := nil;
    raise;
  end;
end;

function IndexOf(const Source, Value; ItemSize, ItemCount: Integer): Integer;
var
  I, J: Integer;
begin
  I := 0;
  J := 0;
  while J < ItemCount do
  begin
    if CompareMem(@Value, Pointer(Integer(Source) + I), ItemSize) then
    begin
      Result := J;
      Exit;
    end;
    Inc(I, ItemSize);
    Inc(J);
  end;
  Result := -1;
end;

function IndexOf(const Int64Array: TInt64Array; Value: Int64): Integer;
begin
  Result := IndexOf(Int64Array, Value, SizeOf(Int64), Length(Int64Array));
end;

function IndexOf(const IntArray: TIntArray; Value: Integer): Integer;
begin
  Result := IndexOf(IntArray, Value, SizeOf(Integer), Length(IntArray));
end;

function IndexOf(const ByteArray: TByteArray; Value: Byte): Integer;
begin
  Result := IndexOf(ByteArray, Value, SizeOf(Byte), Length(ByteArray));
end;

function Delete(var Source, Target; ItemSize, ItemCount, ItemIndex: Integer): Boolean;
begin
  Result := (ItemIndex >= 0) and (ItemIndex < ItemCount);
  if not Result then Exit;
  CopyMemory(Pointer(Target), Pointer(Source), ItemSize * ItemIndex);
  CopyMemory(Pointer(Integer(Target) + ItemSize * ItemIndex), Pointer(Integer(Source) +
    ItemSize * (ItemIndex + 1)), ItemSize * (ItemCount - 1 - ItemIndex));
end;

function Delete(var Int64Array: TInt64Array; Index: Integer): Boolean;
var
  I: Integer;
  New: TInt64Array;
begin
  I := Length(Int64Array);
  SetLength(New, I - 1);
  try
    Result := Delete(Int64Array, New, SizeOf(Int64), I, Index);
    if Result then
    begin
      Int64Array := nil;
      Int64Array := New;
    end
    else New := nil;
  except
    New := nil;
    raise;
  end;
end;

function Delete(var IntArray: TIntArray; Index: Integer): Boolean;
var
  I: Integer;
  New: TIntArray;
begin
  I := Length(IntArray);
  SetLength(New, I - 1);
  try
    Result := Delete(IntArray, New, SizeOf(Integer), I, Index);
    if Result then
    begin
      IntArray := nil;
      IntArray := New;
    end
    else New := nil;
  except
    New := nil;
    raise;
  end
end;

function Delete(var ByteArray: TByteArray; Index: Integer): Boolean;
var
  I: Integer;
  New: TByteArray;
begin
  I := Length(ByteArray);
  SetLength(New, I - 1);
  try
    Result := Delete(ByteArray, New, SizeOf(Byte), I, Index);
    if Result then
    begin
      ByteArray := nil;
      ByteArray := New;
    end
    else New := nil;
  except
    New := nil;
    raise;
  end;
end;

procedure Append(const Source; var Target; ItemSize, SourceItemCount,
  TargetItemCount: Integer);
begin
  CopyMemory(Pointer(Integer(Target) + ItemSize * TargetItemCount),
    Pointer(Source), ItemSize * SourceItemCount);
end;

procedure Append(var Int64Array: TIntArray; const NewArray: TInt64Array);
var
  I, J: Integer;
begin
  I := Length(Int64Array);
  J := Length(NewArray);
  SetLength(Int64Array, I + J);
  Append(NewArray, Int64Array, SizeOf(Int64), J, I);
end;

procedure Append(var IntArray: TIntArray; const NewArray: TIntArray);
var
  I, J: Integer;
begin
  I := Length(IntArray);
  J := Length(NewArray);
  SetLength(IntArray, I + J);
  Append(NewArray, IntArray, SizeOf(Integer), J, I);
end;

procedure Append(var ByteArray: TIntArray; const NewArray: TByteArray);
var
  I, J: Integer;
begin
  I := Length(ByteArray);
  J := Length(NewArray);
  SetLength(ByteArray, I + J);
  Append(NewArray, ByteArray, SizeOf(Byte), J, I);
end;

initialization
  Randomize;

end.
